<template>
    <FormItem
        ref="formitem"
        v-show="!field.isHidden"
        :class="['dci-formitem',field.class,labelPosition?'dci-label-'+labelPosition:'',{'dci-label-width':labelWidth||field.labelWidth},keys]"
        :label="field.label"
        :label-width="field.labelWidth"
        :style="Object.assign({width:field.width},field.style)"
        :prop="prop"
        :rules="formitemRules"
        :data-field-type="field.type"
    >
        <Input
            v-model="field.default"
            v-if=" field.type === 'text' "
            type="text"
            :placeholder="field.placeholder"
            :value="field.default"
            :disabled="field.disabled"
        />

        <Input
            v-model="field.default"
            v-else-if=" field.type === 'number' "
            type="number"
            :placeholder="field.placeholder"
            :value="field.default"
            :disabled="field.disabled"
        />

        <Input
            v-model="field.default"
            v-else-if=" field.type === 'password' "
            type="password"
            :placeholder="field.placeholder"
            :value="field.default"
            :disabled="field.disabled"
        />

        <Input
            v-model="field.default"
            v-else-if=" field.type === 'textarea' "
            type="textarea"
            :placeholder="field.placeholder"
            :value="field.default"
            :autosize="{ minRows: field.minRows, maxRows: field.maxRows }"
            :disabled="field.disabled"
        />

        <DatePicker
            :value="field.default"
            v-else-if=" field.type === 'date' "
            type="date"
            :placeholder="field.placeholder"
            :disabled="field.disabled"
            @on-change="handleChangeDate"
        />

        <Select
            v-model="field.default"
            v-else-if=" field.type === 'select' "
            :placeholder="field.placeholder"
            :value="field.default"
            :disabled="field.disabled"
            :loading="selectLoading"
            :loading-text="loadinigText"
            :class="{'dci-select-cascader': field.cascader}"
            @on-open-change="onSelectOpenChange"
            @on-select="onSelectItem"
        >
            <Option
                v-show=" field.option "
                v-for="(opt,i) in field.option"
                :value="opt.value"
                :key="opt.value"
            >{{ opt.text }}</Option>
        </Select>

        <Select
            v-model="field.default"
            v-else-if=" field.type === 'select2' "
            :placeholder="field.placeholder"
            :value="field.default"
            :disabled="field.disabled"
            multiple
        >
            <Option
                v-show=" field.option "
                v-for="(opt,i) in field.option"
                :value="opt.value"
                :key="opt.value"
                :disabled="field.disabled"
            >{{ opt.text }}</Option>
        </Select>

        <Select
            v-model="field.default"
            v-else-if=" field.type === 'select3' "
            :placeholder="field.placeholder"
            :value="field.default"
            :disabled="field.disabled"
            multiple
        >
            <OptionGroup v-for="(opt,key) in field.option" :key="key" :label="opt.label">
                <Option v-for="item in opt.item" :value="item.BMZ" :key="item.BMZ">{{ item.BMMC }}</Option>
            </OptionGroup>
        </Select>

        <Select
            v-model="field.default"
            v-else-if=" field.type === 'select4' "
            :placeholder="field.placeholder"
            :value="field.default"
            :disabled="field.disabled"
            multiple
        >   
            <template v-for="(opt,key) in field.option">
                <template v-if=" opt.item && opt.item.length>0 ">
                    <OptionGroup :key="key" :label="opt.label">
                        <Option v-for="(child,index) in opt.item" :value="child.BMZ" :key="index">{{ child.BMMC }}</Option>
                    </OptionGroup>
                </template> 
                <template v-else>
                    <Option :value="opt.value" :key="key">{{ opt.label }}</Option>
                </template> 
            </template>            
        </Select>

        <Select
            v-model="field.default"
            v-else-if=" field.type === 'select5' "
            :placeholder="field.placeholder"
            :value="field.default"
            :disabled="field.disabled"
        >   
            <template v-for="(opt,key) in field.option">
                <template v-if=" opt.item && opt.item.length>0 ">
                    <OptionGroup :key="key" :label="opt.label">
                        <Option v-for="(child,index) in opt.item" :value="child.value" :key="index">{{ child.label }}</Option>
                    </OptionGroup>
                </template> 
                <template v-else>
                    <Option :value="opt.value" :key="key">{{ opt.label }}</Option>
                </template> 
            </template>            
        </Select>
        
        <Select
            v-model="field.default"
            v-else-if=" field.type === 'select6' "
            :placeholder="field.placeholder"
            :value="field.default"
            :disabled="field.disabled"
            :loading="selectLoading"
            :loading-text="loadinigText"
            :class="{'dci-select-cascader': field.cascader}"
            @on-open-change="onSelectOpenChange"
            @on-select="onSelectItem"
        >
            <Option
                v-show=" field.option "
                v-for="(opt,i) in field.option"
                :value="opt.value"
                :key="opt.value"
            >{{ opt.text }}</Option>
        </Select>

        <RadioGroup
            v-model="field.default"
            v-else-if=" field.type === 'radio' "
            :placeholder="field.placeholder"
            :value="field.default"
            :disabled="field.disabled"
        >
            <Radio
                v-for="(radio,i) in field.radio"
                :label="radio.val"
                :key="radio.val"
                :disabled="field.disabled"
                :data-key="radio.val"
                border
            >
                <template v-if="radio.poptip">
                    <Poptip
                        trigger="hover"
                        :word-wrap="true"
                        :content="radio.poptip"
                        placement="top"
                    >{{ radio.label }}</Poptip>
                </template>
                <template v-else>{{ radio.label }}</template>
            </Radio>
        </RadioGroup>

        <CheckboxGroup
            v-model="field.default"
            v-else-if=" field.type === 'checkbox' "
            :placeholder="field.placeholder"
            :value="field.default"
            :disabled="field.disabled"
        >
            <Checkbox
                v-for="(checkbox,i) in field.checkbox"
                :label="checkbox.val"
                :key="checkbox.val"
                :disabled="field.disabled"
                border
            >
                <template v-if="checkbox.poptip">
                    <Poptip
                        trigger="hover"
                        :word-wrap="true"
                        :content="checkbox.poptip"
                        placement="top"
                    >{{ checkbox.label }}</Poptip>
                </template>
                <template v-else>{{ checkbox.label }}</template>
            </Checkbox>
        </CheckboxGroup>

        <Button
            v-else-if=" field.type === 'button' "
            :disabled="field.disabled"
            :icon="field.icon"
            @click.native="handleEventsCenter"
        >{{ field.text }}</Button>

        <div
            v-html="field.unit"
            style="position: absolute;top: 4px;right: 10px;bottom: 0px;"
            class="unit"
        >{{ field.unit }}</div>
    </FormItem>
</template>

<script>
export default {
    name: "DCIField",
    data () {
        return {
            selectLoading: false,
            loadinigText: '正在请求...'
        }
    },
    props: {
        // 字段的配置结构
        field: {
            type: Object
        },
        // 字段键名
        keys: {
            type: String
        },
        // 对应表单域 model 里的字段
        prop: {
            type: String
        },
        // （动态表单型专属）表单域标签的位置, 主要作用于样式区分
        'label-position': {
            type: String,
        },
        // （动态表单型专属）表单域标签的宽度, 主要作用于样式区分
        'label-width': {
            type: Number,
        },
        // 获取父组件传递的相关参数, 主要获取配置结构
        param: {
            type: Object
        },
        // 获取校验规则的方法, 从父组件直接传递过来, 以避免在子组件多次引入
        getValidateRule: {
            type: Function
        }
    },
    watch: {

    },
    computed: {
        // 字段校验规则（提供部分默认的校验规则）
        formitemRules () {
            let rule = this.field.validate;

            const TYPE = Object.prototype.toString.call(rule).slice(8, -1);
            switch (TYPE) {
                case 'Undefined':
                case 'Null':
                case 'Boolean':
                    return { required: false };
    
                case 'String':
                    let rules = [];

                    rule.replace(/ /g,'').split(/\||\,|\，/g).forEach((r, i) => {
                        let baseRule = this.getValidateRule(r,this.field);
                        r = r.trim();

                        if ( baseRule ) {
                            rules.push(baseRule);
                        } else {
                            console.warn(`校验规则${r}规则不存在`);
                            return false;
                        }
                    });
                    return rules;
                default:
                    return rule;
            }
        }
    },
    beforeCreate () {

    },
    mounted () {
        
        this.handleFormitemWidth();
    },
    beforeUpdate () {

    },
    updated () {
        this.handleFormitemWidth();
    },
    methods: {
        // 调整字段渲染的宽度
        // 优先级 field.labelWidth > DCIForm的label-width
        handleFormitemWidth () {
            const label = this.$refs.formitem.label;

            if ( label && label !== '' && this.labelPosition !== 'top' ) {
                let labelWidth;
                let formitemElement;

                this.$nextTick(() => {
                    // label加上自定义样式
                    if ( this.field.style ) {
                        let cssText = JSON.stringify(this.field.style).replace(/\{|\}|\,|\"|\'/g,(matchStr)=>{
                            let tokenMap = {
                                '{': '',
                                '}': '',
                                '"': '',
                                '\'': '',
                                ',': ';',
                            };
                            return tokenMap[matchStr];
                        })

                        this.$refs.formitem.$el.firstChild.style.cssText = cssText;
                    }

                    labelWidth = this.$refs.formitem.$el.firstChild.offsetWidth;
                    formitemElement = this.$refs.formitem.$el.lastChild;

                    formitemElement.style.width = `calc(100% - ${labelWidth + 1}px)`
                })
            } else if ( !this.field.label && this.labelWidth )  {
                this.$refs.formitem.$el.lastChild.style.marginLeft = '0px';
            }
            return this;
        },
        // 给日期类型的默认值, 赋上正确值
        handleChangeDate (date) {
            this.$set(this.field,'default',date);
        },
        // 按钮事件调度中心
        handleEventsCenter (field) {
            const TYPEOF =  Object.prototype.toString.call(this.field.func).slice(8,-1);
            
            if ( TYPEOF!=='Function' ) {
                return console.warn('温馨提示：按钮未配置函数方法');
            }
                        
            this.field.func(
                // DCIForm的实例
                this.$parent.$parent,
                // 相关配置字段
                this.param
            );
        },
        // 联动请求服务
        getCascaderServer (pid, field) {
            let url = DCIConfig.wwsq_sjld;
            switch (field.cascader) {
                case 'swprovince':
                case 'swcity':
                case 'swcountry':
                    url = DCIConfig.wwsq_swjgsjld;
                    break;
            }

            return this.$ajax.post(url, {
                jsondt: {
                    ID: pid
                }
            }).then((data) => {
                if (data.zt == "1") {
                    let dt = data.dt || [];
                    dt = dt.map((item)=>{
                        return {
                            value: item.ID,
                            text: item.MC
                        }
                    });
                    this.selectLoading = false;
                    this.$set(this.field,'option',dt);
                } else {
                    this.modal.alert({ content: `联动请求发生错误，如下：${data.msg}` });
                }
            });
        },
        // 下拉框展开或收起时触发
        onSelectOpenChange (isOpen) {
            if ( this.field.cascader && isOpen===true ) {
                this.selectLoading = true;
                let pid = '';
                let prevCascader = null;
                let DCIForm = this.$parent.$parent;
                switch ( this.field.cascader ) {
                    case 'city':
                        prevCascader = 'province';
                        break;
                    case 'country':
                        prevCascader = 'city';
                        break;
                    case 'swcity':
                        prevCascader = 'swprovince';
                        break;
                    case 'swcountry':
                        prevCascader = 'swcity';
                        break;
                    default:
                        prevCascader = '';
                        break;
                }
                // 获取关联字段的ID值
                DCIForm.iteratorNConfig({
                    nConfig: DCIForm.nConfig,
                    tableOnCallback: (table) => {

                    },
                    formOnCallback: (form) => {
                        for (const key in form) {
                            let field = form[key];
                            if ( field.cascader === prevCascader ) {
                                pid = field.default;
                            }
                        }
                    }
                });
                
                this.getCascaderServer(pid, this.field);
            }
        },
        // 选择项目时触发
        onSelectItem (item) {
            if ( this.field.cascader ) {
                let DCIForm = this.$parent.$parent;
                
                DCIForm.iteratorNConfig({
                    nConfig: DCIForm.nConfig,
                    tableOnCallback: (table) => {

                    },
                    formOnCallback: (form) => {
                        for (const key in form) {
                            let field = form[key];
                            
                            // 清空关联的下拉框值
                            if ( this.field.cascader==='province' && ( field.cascader=='city' || field.cascader=='country' ) ) {
                                this.$set(field,'option',[]);
                                this.$set(field,'default',null);
                            } else if ( this.field.cascader==='city' && field.cascader=='country' ) {
                                this.$set(field,'option',[]);
                                this.$set(field,'default',null);
                            }
                        }
                    }
                });
            }
        }
    }
};
</script>
<style src="@assets/css/dci.field.css" scoped></style>
